#include "base/base_buffer.h"
#include "base/channel.h"
#include "base/eventloop.h"
#include "base/log.h"
#include "base/mempool.h"
#include "net/connect.h"

#include <sys/socket.h>
#include <vector>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <cstring>

#include "net/buffer.h"
namespace net_tools::net{

#define to_c(x) reinterpret_cast<char*>(x)
net_tools::base::Memorypool* Buffer::mempool_ = nullptr;
__thread Buffer_reader* Buffer::buffer_reader_ = nullptr;

Buffer::Buffer(net_tools::Eventloop* eventloop,Connect* connect)
  :eventloop_(eventloop),
   connect_(connect),
   fd_(0),
   send_all_(true),
   user_want_close_(false),
   still_have_(false),
   recv_head_len_(0),
   residue_len_(0),
   last_time_head_len_data_len_(0),
   head_send_buf_(nullptr),
   head_recv_buf_(nullptr),
   now_send_buf_(nullptr),
   now_recv_buf_(nullptr)
{
};
void Buffer::Init_channel(net_tools::base::Channel* channel){
  channel_ = channel;
  fd_ = channel_->Get_listenfd();

  head_send_buf_ = Get_new_buf(2);
  now_send_buf_ = head_send_buf_;

  head_recv_buf_ = Get_new_buf(1);
  now_recv_buf_ = head_recv_buf_;

  head_recv_buf_->Insert_next(Get_new_buf(1));
};
net_tools::base::Base_buffer* Buffer::Get_new_buf(int size){
  return new net_tools::base::Base_buffer(size);
};

uint32_t Buffer::Peak(){
  if(!residue_len_){
    Analyze_head();
  }
  return residue_len_;
};

void Buffer::Read_buf_clear(){
  if(head_recv_buf_->Is_empty()){
    if(head_recv_buf_ != now_recv_buf_){
      // 如果不是当前的写区 则后面一定有东西没读
      head_recv_buf_->Clear_index();
      head_recv_buf_ = head_recv_buf_->Get_next();
    }else{
      if(!still_have_){
      // 如果是当前的写区但是这次读写后面没东西了
        head_recv_buf_->Clear_index();
      }
    }
  }
};
void Buffer::Analyze_head(){
  if(head_recv_buf_->Get_read_residue() < _C::NET_BUFFER_LENDATA_SIZE){ // 跨区
    char buf[4] = {};
    int last_data_len = head_recv_buf_->Get_read_residue();

    memcpy(buf,(*head_recv_buf_)[0],last_data_len);
    head_recv_buf_->Clear_index();
    head_recv_buf_ = head_recv_buf_->Get_next();
    memcpy(buf + last_data_len,(*head_recv_buf_)[0],_C::NET_BUFFER_LENDATA_SIZE - last_data_len);
    head_recv_buf_->Read_append(_C::NET_BUFFER_LENDATA_SIZE - last_data_len);
    residue_len_ = *reinterpret_cast<uint32_t*>(buf);
    Read_buf_clear();
  }else{ // 没跨区
    residue_len_ = *reinterpret_cast<uint32_t*>((*head_recv_buf_)[0]);
    head_recv_buf_->Read_append(_C::NET_BUFFER_LENDATA_SIZE);
    Read_buf_clear();
  }
};

int Buffer::Read(void* buf,uint32_t max_size){
  if(!residue_len_){ // 第一次收到这个包
    Analyze_head();
  }
  uint32_t read_len = 0; //这次读的长度
  while(residue_len_ > 0){
    uint32_t now_write = residue_len_ > head_recv_buf_->Get_read_residue() ?
                        head_recv_buf_->Get_read_residue() : residue_len_;
    now_write = now_write > max_size - read_len ? max_size - read_len : now_write;
    memcpy(to_c(buf)+read_len,(*head_recv_buf_)[0],now_write);
    residue_len_ -= now_write;
    head_recv_buf_->Read_append(now_write);
    read_len += now_write;
    Read_buf_clear();
    if(read_len == max_size){ //用户提供的缓冲区满了
      return max_size;
    }
  }
  return read_len;
};

Buffer_reader* Buffer::Read(){
  Analyze_head();
  // buffer_reader_->Init(this);
  return buffer_reader_;
};

void Buffer::Recv(uint32_t len){
  while(len > 0){
    uint32_t now_write = len > now_recv_buf_->Get_write_residue() ?
                         now_recv_buf_->Get_write_residue() : len;
    now_recv_buf_->Write_append(now_write);
    len -= now_write;
    if(now_recv_buf_->Is_full()){
      now_recv_buf_ = now_recv_buf_->Get_next();
    }
  }
};

void Buffer::Read_able_callback(){
  connect_->Rec_heartbeat();
  iovec iovector[_C::BUFFER_ONCE_READ_CALLBACK_IOVEC_SIZE];
  int read_in_int = Read_from_fd(iovector);
  if(read_in_int <= 0){
    return;
  }
  uint32_t read_in = static_cast<uint32_t>(read_in_int);
  read_in -= Build_head(read_in);
  while(read_in){
    if(recv_head_len_ > 0){ //还有数据没读完
      uint32_t now_write = recv_head_len_ > read_in ? read_in : recv_head_len_;
      recv_head_len_ -= now_write;
      read_in -= now_write;
      Recv(now_write);
      if(recv_head_len_ == 0){ //收到整包
        still_have_ = static_cast<bool>(read_in);
        read_callback_(connect_);
        // buffer_reader_->Read_all();
        read_in -= Build_head(read_in);
      }
    }else if(recv_head_len_ == 0){ //收到心跳包
      read_in -= Build_head(read_in);
    }
  }
};

int Buffer::Read_from_fd(iovec* iovector){
  int iovector_number = 0;
  net_tools::base::Base_buffer* now_buf = now_recv_buf_;
  for(;iovector_number < _C::BUFFER_ONCE_READ_CALLBACK_IOVEC_SIZE;){
    if(!now_buf->Is_full()){ // 如果当前区没满 则可以写入
      iovector[iovector_number].iov_base = now_buf->Write_index();
      iovector[iovector_number].iov_len = now_buf->Get_write_residue();
      ++iovector_number;
    }
    now_buf = now_buf->Get_next();
    if(now_buf == head_recv_buf_){ //自增后等于头部 没缓冲区了
      now_buf->Insert_pre(Get_new_buf(1));
      now_buf = now_buf->Get_pre();
    }
  }
  int read_in_len = readv(fd_,iovector,iovector_number);
  if(read_in_len <= 0) [[unlikely]] { //被瞬间关闭
    Close_callback();
    return -1;
  }
  return read_in_len;
};

int Buffer::Build_head(uint32_t len){
  if(recv_head_len_ == 0 && len >= _C::NET_BUFFER_LENDATA_SIZE - last_time_head_len_data_len_){ //还没建立起头 且收到的长度够建立起包头
    int len_size = _C::NET_BUFFER_LENDATA_SIZE - last_time_head_len_data_len_;
    if(now_recv_buf_->Get_write_index() - last_time_head_len_data_len_ < 0 ||
       now_recv_buf_->Get_write_index() - last_time_head_len_data_len_ > now_recv_buf_->Get_buf_size() - _C::NET_BUFFER_LENDATA_SIZE){ // 跨区了
      Recv(len_size);
      int last_buffer_data_len = _C::NET_BUFFER_LENDATA_SIZE - now_recv_buf_->Get_write_index();
      char buf[4] = {};
      net_tools::base::Base_buffer* pre = now_recv_buf_->Get_pre();
      memcpy(buf,pre->Write_index() - last_buffer_data_len,last_buffer_data_len);
      memcpy(buf + last_buffer_data_len,(*now_recv_buf_)[0],now_recv_buf_->Get_write_index());

      recv_head_len_ = *reinterpret_cast<uint32_t*>(buf);
      last_time_head_len_data_len_ = 0;
    }else{ // 没有跨区
      recv_head_len_ = *reinterpret_cast<uint32_t*>(now_recv_buf_->Write_index(-last_time_head_len_data_len_));
      last_time_head_len_data_len_ = 0;
      Recv(len_size);
    }
    return len_size;
  }else if(recv_head_len_ == 0){ //还没建立起头 长度不够
    last_time_head_len_data_len_ += len;
    Recv(len);
    return len;
  }
  return 0;
};

void Buffer::Send(){
  int write_in_len = Write_in_fd();
  if(write_in_len == -1){
    return;
  }
  uint32_t write_in = static_cast<uint32_t>(write_in_len);
  for(;;){
    uint32_t len = head_send_buf_->Get_read_residue();
    if(write_in > len){
      //还有 循环队列
      head_send_buf_->Clear_index();
      head_send_buf_ = head_send_buf_->Get_next();
      write_in -= len;
    }else if(write_in == len){
      // 最后一个
      head_send_buf_->Clear_index();
      break;
    }else{
      //等待下一轮发送
      head_send_buf_->Read_append(write_in);
      channel_->Enablewrite();
      eventloop_->Modevent(channel_);
    }
  }
  send_all_ = true;
  channel_->Disablewrite();
  eventloop_->Modevent(channel_);
};

void Buffer::Append(void* buf,uint32_t len){
  uint32_t need_write = len;
  uint32_t already_write = 0;
  send_all_ = false;
  while(need_write > 0){
    uint32_t now_write;
    now_write = need_write > now_send_buf_->Get_write_residue() ?
                now_send_buf_->Get_write_residue() : need_write;
    now_send_buf_->Write(to_c(buf)+already_write,now_write);
    already_write += now_write;
    need_write -= now_write;
    if(now_send_buf_->Is_full() && need_write > 0){
      now_send_buf_ = now_send_buf_->Get_next();
      if(now_send_buf_ == head_send_buf_){ // 没区了
        now_send_buf_->Insert_pre(Get_new_buf(1));
        now_send_buf_ = now_send_buf_->Get_pre();
      }
    }
  }
};

bool Buffer::Write(net_tools::base::Base_buffer* base_buffer){
  return true;
};

bool Buffer::Write(void* buf,uint32_t len){
  if(user_want_close_) [[unlikely]] {
    return false;
  }
  if(!send_all_){ //缓冲区不为空 之前的还没被发送
    Append(to_c(&len),_C::NET_BUFFER_LENDATA_SIZE);
    Append(buf,len);
    return true;
  }else{ //缓冲区里没东西了 send_all为true
    iovec iovector[2];
    iovector[0].iov_base = &len;
    iovector[0].iov_len = _C::NET_BUFFER_LENDATA_SIZE;
    iovector[1].iov_base = buf;
    iovector[1].iov_len = len;
    int write_in_len = writev(fd_,iovector,2);
    if(write_in_len == -1) [[unlikely]] {
      if(errno != EWOULDBLOCK){ // 不是满了的原因
        Clean_buffer();
        close_callback_(connect_);
        return false;
      }else{
        write_in_len = 0;
      }
    }
    uint32_t already_write = static_cast<uint32_t>(write_in_len);
    if(already_write < len + _C::NET_BUFFER_LENDATA_SIZE){ // 还有东西没写完
      if(already_write < _C::NET_BUFFER_LENDATA_SIZE) [[unlikely]] { //如果连头都没写完
        Append(to_c(&len) + already_write,_C::NET_BUFFER_LENDATA_SIZE - already_write);
        already_write = _C::NET_BUFFER_LENDATA_SIZE;
      }
      Append(to_c(buf) + already_write - _C::NET_BUFFER_LENDATA_SIZE,len + _C::NET_BUFFER_LENDATA_SIZE - already_write);
      channel_->Enablewrite();
      eventloop_->Modevent(channel_);
    }
    return true;
  }
};

int Buffer::Write_in_fd(){
  iovec iovector[_C::BUFFER_ONCE_WRITE_CALLBACK_IOVEC_SIZE];
  int iovector_number = 0;
  net_tools::base::Base_buffer* now_buf = head_send_buf_;
  for(;iovector_number < _C::BUFFER_ONCE_WRITE_CALLBACK_IOVEC_SIZE;){
    iovector[iovector_number].iov_base = (*now_buf)[0];
    iovector[iovector_number].iov_len = now_buf->Get_read_residue();
    ++iovector_number;
    if(!now_buf->Is_full()){ //不满 没数据了
      break;
    }
    now_buf = now_buf->Get_next();
  }
  int write_in_len = writev(fd_,iovector,iovector_number);
  if(write_in_len == -1) [[unlikely]] { //fd_ 被瞬间关闭
    Close_callback();
    return -1;
  }
  return write_in_len;
};

void Buffer::Write_able_callback(){
  int write_in_len = Write_in_fd();
  if(write_in_len == -1){
    return;
  }
  uint32_t write_in = static_cast<uint32_t>(write_in_len);
  if(write_in == 0){
    return;
  }
  for(;;){
    uint32_t len = head_send_buf_->Get_read_residue();
    if(write_in > len){
      //还有 循环队列
      head_send_buf_->Clear_index();
      head_send_buf_ = head_send_buf_->Get_next();
      write_in -= len;
    }else if(write_in == len){
      head_send_buf_->Clear_index();
      if(head_send_buf_ != now_send_buf_){
      // 不是最后一个 恰巧写完
        head_send_buf_ = head_send_buf_->Get_next();
        write_in -= len;
        continue;
      }
      if(user_want_close_){
        User_want_close();
        return;
      }
      break;
    }else{
      //等待下一轮发送
      head_send_buf_->Read_append(write_in);
      return;
    }
  }
  send_all_ = true;
  channel_->Disablewrite();
  eventloop_->Modevent(channel_);
};


void Buffer::Close(){
  //用户想关闭了 要把用户里的包都发完
  if(!send_all_){ //还没发完 已经监听可写
    user_want_close_ = true;
  }else{
    User_want_close();
  }
};
void Buffer::Close_right_now(){
  User_want_close();
};

void Buffer::Clean_buffer(){
  if(head_send_buf_){
    for(net_tools::base::Base_buffer* begin = head_send_buf_->Get_next();begin != head_send_buf_;begin = begin->Get_next()){
      delete begin;
    }
    delete head_send_buf_;
  }
  if(head_recv_buf_){
    for(net_tools::base::Base_buffer* begin = head_recv_buf_->Get_next();begin != head_recv_buf_;begin = begin->Get_next()){
      delete begin;
    }
    delete head_recv_buf_;
  }
  head_send_buf_ = nullptr;
  head_recv_buf_ = nullptr;
  now_recv_buf_ = nullptr;
  now_send_buf_ = nullptr;
  send_all_ = true;
  user_want_close_ = false;
  still_have_ = false;
  recv_head_len_ = 0;
  residue_len_ = 0;
  last_time_head_len_data_len_ = 0;
  NT_LOG_INFO << "clean buffer" << NT_LOG_ENDL;
};
void Buffer::Close_callback(){
  NT_LOG_TRACE << "Close_call_back" << NT_LOG_ENDL;
  Clean_buffer();
  close_callback_(connect_);
};

void Buffer::User_want_close(){
  Clean_buffer();
  user_want_close_callback_(connect_);
};

void Buffer::Set_able_read_callback(connect_func cb){
  read_callback_ = std::move(cb);
};
void Buffer::Set_able_close_callback(connect_func cb){
  close_callback_ = std::move(cb);
};
void Buffer::Set_able_user_close_callback(connect_func cb){
  user_want_close_callback_ = std::move(cb);
};

} // namespace net_tools::net